#!/usr/bin/env python3
# $Id: test3-12.py 0c81aa997100 2012/09/03 07:53:27 pgurumur $
# Copyright (c) 2012 Prabhu Gurumurthy <pgurumur@gmail.com>
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#

__version__  = "$Revision: 0c81aa997100 $"
__author__   = "$Author: pgurumur $"
__modified__ = "$Date: 2012-09-03 07:53:27Z $"

import heapq
import itertools

class Task(object):
   def __init__(self):
      super(Task, self).__init__()
      self._pq = []
      self._entry = {}
      self._counter = itertools.count()
      self._removed = "<>"

   def add(self, task, priority = 0):
      if task:
         if task in self._entry:
            self.remove(task)

         count = next(self._counter)
         entry = [priority, count, task]
         self._entry[task] = entry
         heapq.heappush(self._pq, entry)

   def remove(self, task):
      if task:
         entry = self._entry.pop(task)
         entry[-1] = self._removed

   def pop(self):
      retval = None
      while self._pq:
         priority, count, task = heappop(self._pq)
         if task is not self._removed:
            del self._entry[task]
            retval = task
            break

      if retval is None:
         raise KeyError("priority queue is empty")

      return retval

   def __add__(self, task):
      self.add(task, 0)
      return self

   def __sub__(self, task):
      self.remove(task)
      return self
